package main

import "fmt"

func main() {
	myprintAdd(4, 5)

	fmt.Println(juadegeType("world", 10))

	x, y := swap("hello", "world")

	fmt.Println(x, y)

	fmt.Printf("getSum is %d \n", getSum(1, 2, 3, 4, 5, 6))

	// 值传递
	// arr2 是arr1 复制来的，所以是不同的空间
	// 修改arr2 并不会影响arr1
	// 值传递，传递是数据的副本，修改数据对于原始数据没有影响
	// 值类型的数据，默认都是值传递的类型有 基础类型，array, struct

	//定义一个数组类型
	arr1 := [4]int{1, 2, 3, 4}

	fmt.Println(updateArr(arr1))

	// 延迟到最后再执行
	defer f(10000)

	// 定义一个切片类型
	s1 := []int{1, 2, 3, 4}

	fmt.Println("s1 修改前的值", s1)
	updateSlice(s1)
	fmt.Println("s1 修改后的值", s1)

	// 自己调用自己的函数
	func(a, b int) {
		fmt.Println(a + b)
	}(10, 20)

	r := oper(50, 20, func(a, b int) int {
		return a + b
	})

	fmt.Println(r)

	// go 语言的函数闭包
	i1 := increment()

	fmt.Println(i1()) // 本来i1执行完毕之后会销毁，但是由于闭包结构，increment 定义的变量不会销毁释放，会继续执行

	fmt.Println(i1())
	fmt.Println(i1())
	fmt.Println(i1())

	i2 := increment()
	fmt.Println(i2())
	fmt.Println(i2())

	fmt.Println(i1())
	fmt.Println(i2())

}

func myprintAdd(a, b int) {
	fmt.Printf("%d \n", add(a, b))
}

func add(a, b int) int {
	return a + b
}

// 不同类型的菜蔬， 返回一个值
func juadegeType(a string, b int) string {
	if a == "hell" {
		return a
	}
	if b == 10 {
		return a
	}
	return "not found"
}

// 返回两个值
func swap(a, b string) (string, string) {
	return b, a
}

// 可变参数
func getSum(nums ...int) int {
	sum := 0

	for i := 0; i < len(nums); i++ {
		sum = sum + nums[i]
	}
	return sum
}

// 值传递

func updateArr(arr2 [4]int) [4]int {
	arr2[2] = 100
	return arr2
}

// 引用传递

func updateSlice(s2 []int) []int {
	fmt.Println("s2修改前的值", s2)
	s2[0] = 100
	fmt.Println("s2修改后的值", s2)
	return s2
}

// defer 推迟，延迟执行函数，到最后再进行执行

func f(num int) {
	fmt.Println(num)
}

// 匿名函数

var f1 = func() {
	fmt.Printf("我是f1")
}

//go 语言里面的回调函数  和 js 类似

func oper(a, b int, fun func(int, int) int) int {
	r := fun(a, b)
	return r

}

// go 语言的闭包和 js类似

func increment() func() int {
	i := 0
	fun := func() int {
		i++
		return i
	}
	return fun
}
